/**
  ******************************************************************
  * @file    main.c
  * @author  merlin
  * @version V1.0
  * @date    2022-5-10
  * @brief   ADC，WS2812B
  ******************************************************************
  * @attention
  * verimake 用于
  * 用旋转电位器调节WS2812B灯带亮度
  ******************************************************************
  */
#include <CH549_sdcc.h>  //ch549的头文件，其中定义了单片机的一些特殊功能寄存器
#include <CH549_DEBUG.h> //CH549官方提供库的头文件，定义了一些关于主频，延时，串口设置，看门口，赋值设置等基础函数
#include <CH549_ADC.h>   //CH549官方提供库的头文件，定义了一些关于ADC初始化，采集数据等函数
/********************************************************************
* TIPS:
* adc各通道对应引脚关系
* P1.1       AIN1
* P1.2       AIN2
* P1.3       AIN3
* P1.4       AIN4
* P1.5       AIN5
* P1.6       AIN6
* P1.7       AIN7
* P0.0       AIN8
* P0.1       AIN9
* P0.2       AIN10  
* P0.3       AIN11 
* P0.4       AIN12 
* P0.5       AIN13 
* P0.6       AIN14 
* P0.7       AIN15 
*********************************************************************/
#define WS2812 P2_2                           //设定p2.2口作为灯带的输入口
#define _nop() __asm NOP __endasm             //将nop指令定义为宏

//1码，高电平850ns 低电平400ns 误差正负150ns
#define RGB_1() do{WS2812 = 1;\
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
	WS2812 = 0;}while(0)                                                               //此处加do while循环可以将宏定义的部分可以被识别为语句，方便纠错

//0码，高电平400ns 低电平850ns 误差正负150ns
#define RGB_0() do{WS2812 = 1;\
		_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
        _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
		WS2812 = 0;\
		_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();\
		_nop();_nop();_nop();_nop();_nop();}while(0)

#define numLEDs 14   //灯的个数
UINT8 buf_R[numLEDs] = {0};//颜色缓存
UINT8 buf_G[numLEDs] = {0};
UINT8 buf_B[numLEDs] = {0};


/*****************由于函数的运算的原因导致低电平的时间超过了时序要求，所以用宏定义代替函数缩短运算时间。若本身低电平时间满足要求即可仍然使用函数定义
//1码，高电平850ns 低电平400ns 误差正负150ns
void RGB_Set_Up() 
{
		WS2812 = 1;
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();
    _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();
    _nop();_nop();_nop();_nop();_nop();
		WS2812 = 0;
}
 
//0码，高电平400ns 低电平850ns 误差正负150ns
void RGB_Set_Down() 
{
		WS2812 = 1;
		_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();
        _nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();_nop();

		WS2812 = 0;
}*****************/
//发送24位数据
void Send_2811_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
{
	  
	  char n = 0;
	  //发送G8位
		for(n=0;n<8;n++)
		{
			
			if(G8&0x80)
			{
				RGB_1();
			}
			else  
			{
			  RGB_0();
			}
      G8<<=1;
		}
		//发送R8位
		for(n=0;n<8;n++)
		{
			
			if(R8&0x80)
			{
				RGB_1();
			}
			else  
			{
				RGB_0();
			}
			R8<<=1;
		}
		//发送B8位
	  for(n=0;n<8;n++)
		{
		
			if(B8&0x80)
			{
				RGB_1();
			}
			else  
			{
			  RGB_0();
			}
      	B8<<=1;
		}
}

//复位码
void RGB_Rst()
{
		WS2812 = 0;
		mDelayuS( 50 );
}

//将颜色数据放入缓存之后再输出，以后进一步增加功能时可以用上
void Set_Colour(unsigned char r,unsigned char g,unsigned char b)
{
	  unsigned char i;
		for(i=0;i<numLEDs;i++)
	  {
			  buf_R[i] = r; //缓冲
			  buf_G[i] = g;
			  buf_B[i] = b;
		}
		for(i=0;i<numLEDs;i++)
		{
			Send_2811_24bits(buf_G[i],buf_R[i],buf_B[i]);//发送显示
		}
}

//直接将颜色数据赋予灯带
void Set_Light(unsigned char x,unsigned char y,unsigned char z)
{
unsigned char i;
for ( i = 0; i < numLEDs; i++)
{
Send_2811_24bits( x , y , z );//发送显示
}


}
/********************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*********************************************************************/
void main(void)
{
  UINT8 ch;
  UINT16 Voltage;
  CfgFsys(); //CH549时钟选择配置
  mDelaymS(20);
  ADC_ExInit(3); //ADC初始化,选择采样时钟
  /* 主循环 */
  while (1)
  {
    ch = 7;            //选择P1.7口作为ADC的采样口
    ADC_ChSelect(ch);  //选择通道
    ADC_StartSample(); //启动采样
	
    while ((ADC_CTRL & bADC_IF) == 0)
    {
      ; //查询等待标志置位
    }
    ADC_CTRL = bADC_IF; //清标志2
    Voltage = ADC_DAT * 255.0 / 4095.0;                      //由于voltage数据类型的原因，先乘后除可以避免出现除法之后只有0和1再乘会出现灯带闪烁的情况
    /*
    adc采集到的值为ADC_DAT，由于ch549是12位ADC模数转换器因此ADC_DAT为0-4095之间的数，它表达的含义是电压值的相对高低
    因此 实际电压值的算法为ADC_DAT乘255除以4095以ch549所使用的亮度
    */
    //Set_Colour( 0Xff , 0X00 , 0X00 );
	if (Voltage > 32 )                                  //voltage值大于32时打开灯
	{
	Set_Light(Voltage,Voltage,Voltage );                //根据voltage值赋予灯亮度
	mDelaymS(30);                                       //WS2812B需要一小段延迟将数据写入
	}
	else  
	{
	Set_Light(0x00,0x00,0x00 );
	mDelaymS(30);
	}
	
//   Set_Light(Voltage,Voltage,Voltage );
//    mDelayuS(500);
  }
}